#pragma once
#include<iostream>
#include<poll.h>
#include"Socket.hpp"
#include"InetAddr.hpp"
#include"log.hpp"


class PollServer
{
public:
	static const int gnum = sizeof(fd_set)*8;
	static const int gdefaultfd = -1;
	PollServer(uint16_t port):_port(port),_listensock(make_unique<TcpSocket>())
	{
		_listensock->BuildListenSocket(port);
	};
	void InitServer()
	{
		fd_events[0].fd = _listensock->Sockfd();
		fd_events[0].events = POLLIN;
		fd_events[0].revents = 0;
		for(int i =1;i<gnum;i++)
		{
			fd_events[i].fd = gdefaultfd;
			fd_events[i].events=0;
			fd_events[i].revents = 0;
		};
	};
	void Accepter()
	{
		InetAddr addr;
		int sockfd = _listensock->Accepter(&addr);

		LOG(DEBUG, "get a new link, client info %s:%d\n", addr.Ip().c_str(), addr.Port());
		if(sockfd>0)
		{
			int i =0;
			for(;i<gnum;i++)
			{
				if(fd_events[i].fd==gdefaultfd)
				{
					fd_events[i].fd=sockfd;
					fd_events[i].events = POLLIN;
					LOG(INFO, "add %d to fd_array success!\n", sockfd);
					break;
				};
			}
			if(i==gnum)
			{
				//如果不想限制文件描述符的个数的话，这里可以直接扩容
				LOG(ERROR,"fd_array full!\n");
				close(sockfd);

			};
		};
	};
	void HandlerIO(int i )
	{
		char buffer[1024];
		ssize_t n = recv(fd_events[i].fd,buffer,sizeof(buffer)-1,0);
		if(n>0)
		{
			buffer[n] = 0;
			cout<<fd_events[i].fd<<"said:"<<buffer<<endl;

		}
		else if(n==0)
		{
			LOG(INFO,"%d: quit\n",fd_events[i].fd);
			fd_events[i].fd =gdefaultfd;
			fd_events[i].events = 0;
			fd_events[i].revents = 0;
			close(fd_events[i].fd);
		}
		else
		{
			LOG(ERROR,"%d: error\n",fd_events[i].fd);
			fd_events[i].fd =gdefaultfd;
			fd_events[i].events = 0;
			fd_events[i].revents = 0;
			close(fd_events[i].fd);
		};
	};
	void HandlerEvent()
	{
		for(int i =0;i<gnum;i++)
		{
			if(fd_events[i].fd==gdefaultfd)
				continue;
			if(fd_events[i].revents&POLLIN)
			{
				if(fd_events[i].fd ==_listensock->Sockfd())
					Accepter();
				else
					HandlerIO(i);
			}
		};

	};
	void PrintDebug()
	{
		cout<<"fd list:";
		for(int i =0;i<gnum;i++)
			if(fd_events[i].fd!=gdefaultfd)
				cout<<" "<<fd_events[i].fd;
		cout<<endl;
	};
	void Loop()
	{
		int timeout =-1;
		while(true)
		{
			int n = poll(fd_events,gnum,timeout);
			if(n>0)
			{
				LOG(INFO,"exist event ready! \n");
				HandlerEvent();
				PrintDebug();

			}
			else if(n==0)
			{
				LOG(INFO,"time out\n");
			}
			else
			{
				LOG(ERROR,"pool error\n");
			};
		};
	};
		




private:
	uint16_t _port;
	unique_ptr<Socket> _listensock;
	struct pollfd fd_events[gnum];
};
